package com.brzjomo.embraceofthevoid.blocks;

import com.brzjomo.embraceofthevoid.EmbraceOfTheVoid;
import com.brzjomo.embraceofthevoid.blocks.entity.VillagerAltarEntity;
import com.brzjomo.embraceofthevoid.init.ModBlockEntityTypes;
import net.minecraft.block.*;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.block.entity.BlockEntityTicker;
import net.minecraft.block.entity.BlockEntityType;
import net.minecraft.block.entity.FurnaceBlockEntity;
import net.minecraft.client.item.TooltipContext;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.fluid.FluidState;
import net.minecraft.fluid.Fluids;
import net.minecraft.item.ItemPlacementContext;
import net.minecraft.item.ItemStack;
import net.minecraft.screen.NamedScreenHandlerFactory;
import net.minecraft.stat.Stats;
import net.minecraft.state.StateManager;
import net.minecraft.state.property.BooleanProperty;
import net.minecraft.state.property.Properties;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
import net.minecraft.util.function.BooleanBiFunction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.shape.VoxelShape;
import net.minecraft.util.shape.VoxelShapes;
import net.minecraft.world.BlockView;
import net.minecraft.world.World;
import net.minecraft.world.WorldAccess;
import org.jetbrains.annotations.Nullable;

import java.util.List;
import java.util.Objects;
import java.util.stream.Stream;

public class VillagerAltar extends AbstractFurnaceBlock implements Waterloggable {
    public static final BooleanProperty WATERLOGGED = Properties.WATERLOGGED;
    private static final VoxelShape SHAPE_N = Stream.of(
            Block.createCuboidShape(4, 11, 5, 12, 22, 11),
            Block.createCuboidShape(7, 21, 2, 9, 25, 4),
            Block.createCuboidShape(4, 22, 4, 12, 32, 12),
            Block.createCuboidShape(8, 1, 6, 11.5, 13, 10),
            Block.createCuboidShape(4.5, 1, 6, 8, 13, 10),
            Block.createCuboidShape(3.9, 2.9, 4.9, 12.1, 22.1, 11.1),
            Block.createCuboidShape(13, 6, 3, 16, 8, 6),
            Block.createCuboidShape(13, 6, 6, 16, 9, 10),
            Block.createCuboidShape(13, 6, 10, 16, 8, 13),
            Block.createCuboidShape(0, 6, 10, 3, 8, 13),
            Block.createCuboidShape(0, 6, 6, 3, 9, 10),
            Block.createCuboidShape(0, 6, 3, 3, 8, 6),
            Block.createCuboidShape(13, 6, 13, 16, 9, 16),
            Block.createCuboidShape(10, 6, 13, 13, 8, 16),
            Block.createCuboidShape(6, 6, 13, 10, 9, 16),
            Block.createCuboidShape(3, 6, 13, 6, 8, 16),
            Block.createCuboidShape(0, 6, 13, 3, 9, 16),
            Block.createCuboidShape(0, 6, 0, 3, 9, 3),
            Block.createCuboidShape(3, 6, 0, 6, 8, 3),
            Block.createCuboidShape(6, 6, 0, 10, 9, 3),
            Block.createCuboidShape(10, 6, 0, 13, 8, 3),
            Block.createCuboidShape(13, 6, 0, 16, 9, 3),
            Block.createCuboidShape(0, 0, 0, 16, 6, 16)
    ).reduce((v1, v2) -> VoxelShapes.combineAndSimplify(v1, v2, BooleanBiFunction.OR)).get();
    private static final VoxelShape SHAPE_S = Stream.of(
            Block.createCuboidShape(4, 11, 5, 12, 22, 11),
            Block.createCuboidShape(7, 21, 12, 9, 25, 14),
            Block.createCuboidShape(4, 22, 4, 12, 32, 12),
            Block.createCuboidShape(4.5, 1, 6, 8, 13, 10),
            Block.createCuboidShape(8, 1, 6, 11.5, 13, 10),
            Block.createCuboidShape(3.9, 2.9, 4.9, 12.1, 22.1, 11.1),
            Block.createCuboidShape(0, 6, 10, 3, 8, 13),
            Block.createCuboidShape(0, 6, 6, 3, 9, 10),
            Block.createCuboidShape(0, 6, 3, 3, 8, 6),
            Block.createCuboidShape(13, 6, 3, 16, 8, 6),
            Block.createCuboidShape(13, 6, 6, 16, 9, 10),
            Block.createCuboidShape(13, 6, 10, 16, 8, 13),
            Block.createCuboidShape(0, 6, 0, 3, 9, 3),
            Block.createCuboidShape(3, 6, 0, 6, 8, 3),
            Block.createCuboidShape(6, 6, 0, 10, 9, 3),
            Block.createCuboidShape(10, 6, 0, 13, 8, 3),
            Block.createCuboidShape(13, 6, 0, 16, 9, 3),
            Block.createCuboidShape(13, 6, 13, 16, 9, 16),
            Block.createCuboidShape(10, 6, 13, 13, 8, 16),
            Block.createCuboidShape(6, 6, 13, 10, 9, 16),
            Block.createCuboidShape(3, 6, 13, 6, 8, 16),
            Block.createCuboidShape(0, 6, 13, 3, 9, 16),
            Block.createCuboidShape(0, 0, 0, 16, 6, 16)
    ).reduce((v1, v2) -> VoxelShapes.combineAndSimplify(v1, v2, BooleanBiFunction.OR)).get();
    private static final VoxelShape SHAPE_E = Stream.of(
            Block.createCuboidShape(5, 11, 4, 11, 22, 12),
            Block.createCuboidShape(12, 21, 7, 14, 25, 9),
            Block.createCuboidShape(4, 22, 4, 12, 32, 12),
            Block.createCuboidShape(6, 1, 8, 10, 13, 11.5),
            Block.createCuboidShape(6, 1, 4.5, 10, 13, 8),
            Block.createCuboidShape(4.9, 2.9, 3.9, 11.1, 22.1, 12.1),
            Block.createCuboidShape(10, 6, 13, 13, 8, 16),
            Block.createCuboidShape(6, 6, 13, 10, 9, 16),
            Block.createCuboidShape(3, 6, 13, 6, 8, 16),
            Block.createCuboidShape(3, 6, 0, 6, 8, 3),
            Block.createCuboidShape(6, 6, 0, 10, 9, 3),
            Block.createCuboidShape(10, 6, 0, 13, 8, 3),
            Block.createCuboidShape(0, 6, 13, 3, 9, 16),
            Block.createCuboidShape(0, 6, 10, 3, 8, 13),
            Block.createCuboidShape(0, 6, 6, 3, 9, 10),
            Block.createCuboidShape(0, 6, 3, 3, 8, 6),
            Block.createCuboidShape(0, 6, 0, 3, 9, 3),
            Block.createCuboidShape(13, 6, 0, 16, 9, 3),
            Block.createCuboidShape(13, 6, 3, 16, 8, 6),
            Block.createCuboidShape(13, 6, 6, 16, 9, 10),
            Block.createCuboidShape(13, 6, 10, 16, 8, 13),
            Block.createCuboidShape(13, 6, 13, 16, 9, 16),
            Block.createCuboidShape(0, 0, 0, 16, 6, 16)
    ).reduce((v1, v2) -> VoxelShapes.combineAndSimplify(v1, v2, BooleanBiFunction.OR)).get();
    private static final VoxelShape SHAPE_W = Stream.of(
            Block.createCuboidShape(5, 11, 4, 11, 22, 12),
            Block.createCuboidShape(2, 21, 7, 4, 25, 9),
            Block.createCuboidShape(4, 22, 4, 12, 32, 12),
            Block.createCuboidShape(6, 1, 4.5, 10, 13, 8),
            Block.createCuboidShape(6, 1, 8, 10, 13, 11.5),
            Block.createCuboidShape(4.9, 2.9, 3.9, 11.1, 22.1, 12.1),
            Block.createCuboidShape(3, 6, 0, 6, 8, 3),
            Block.createCuboidShape(6, 6, 0, 10, 9, 3),
            Block.createCuboidShape(10, 6, 0, 13, 8, 3),
            Block.createCuboidShape(10, 6, 13, 13, 8, 16),
            Block.createCuboidShape(6, 6, 13, 10, 9, 16),
            Block.createCuboidShape(3, 6, 13, 6, 8, 16),
            Block.createCuboidShape(13, 6, 0, 16, 9, 3),
            Block.createCuboidShape(13, 6, 3, 16, 8, 6),
            Block.createCuboidShape(13, 6, 6, 16, 9, 10),
            Block.createCuboidShape(13, 6, 10, 16, 8, 13),
            Block.createCuboidShape(13, 6, 13, 16, 9, 16),
            Block.createCuboidShape(0, 6, 13, 3, 9, 16),
            Block.createCuboidShape(0, 6, 10, 3, 8, 13),
            Block.createCuboidShape(0, 6, 6, 3, 9, 10),
            Block.createCuboidShape(0, 6, 3, 3, 8, 6),
            Block.createCuboidShape(0, 6, 0, 3, 9, 3),
            Block.createCuboidShape(0, 0, 0, 16, 6, 16)
    ).reduce((v1, v2) -> VoxelShapes.combineAndSimplify(v1, v2, BooleanBiFunction.OR)).get();

    public VillagerAltar(Settings settings) {
        super(settings);
        this.setDefaultState(this.stateManager.getDefaultState().with(WATERLOGGED, false));
    }

    @Override
    public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
        return switch (state.get(FACING)) {
            default -> SHAPE_N;
            case SOUTH -> SHAPE_S;
            case EAST -> SHAPE_E;
            case WEST -> SHAPE_W;
        };
    }

    @Override
    protected void openScreen(World world, BlockPos pos, PlayerEntity player) {
        BlockEntity blockEntity = world.getBlockEntity(pos);
//        if (blockEntity instanceof VillagerAltarEntity) {
//            player.openHandledScreen((NamedScreenHandlerFactory) blockEntity);
//            player.incrementStat(Stats.INTERACT_WITH_FURNACE);
//        }
    }

    @Nullable
    @Override
    public BlockEntity createBlockEntity(BlockPos pos, BlockState state) {
        return new VillagerAltarEntity(pos, state);
    }

    @Nullable
    @Override
    public <T extends BlockEntity> BlockEntityTicker<T> getTicker(World world, BlockState state, BlockEntityType<T> type) {
        return checkType(type, ModBlockEntityTypes.VILLAGER_ALTAR_ENTITY, VillagerAltarEntity::tick);
    }

    @Override
    public BlockState getStateForNeighborUpdate(BlockState state, Direction direction, BlockState neighborState, WorldAccess world, BlockPos pos, BlockPos neighborPos) {
        if (state.get(WATERLOGGED)) {
            world.scheduleFluidTick(pos, Fluids.WATER, Fluids.WATER.getTickRate(world));
        }
        return super.getStateForNeighborUpdate(state, direction, neighborState, world, pos, neighborPos);
    }

    @Override
    public FluidState getFluidState(BlockState state) {
        if (state.get(WATERLOGGED)) {
            return Fluids.WATER.getStill(false);
        }
        return super.getFluidState(state);
    }

    @Override
    protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
        builder.add(WATERLOGGED);
        super.appendProperties(builder);
    }

    @Override
    public BlockState getPlacementState(ItemPlacementContext ctx) {
        FluidState fluidState = ctx.getWorld().getFluidState(ctx.getBlockPos());
        return Objects.requireNonNull(super.getPlacementState(ctx)).with(WATERLOGGED, fluidState.getFluid() == Fluids.WATER);
    }

    @Override
    public void appendTooltip(ItemStack stack, @Nullable BlockView world, List<Text> tooltip, TooltipContext options) {
        tooltip.add(Text.translatable("block." + EmbraceOfTheVoid.MOD_ID + ".villager_altar" + ".description").formatted(Formatting.WHITE));
        tooltip.add(Text.translatable("block." + EmbraceOfTheVoid.MOD_ID + ".villager_altar" + ".description" + ".2").formatted(Formatting.ITALIC).formatted(Formatting.DARK_GRAY));

        super.appendTooltip(stack, world, tooltip, options);
    }
}
